Fallback Modules
Overview
Fallback modules (IFallback) handle unknown function calls and provide default behavior for smart accounts, particularly useful for token reception and custom fallback logic.
Interface Definition
interface IFallback is IModule {
// Core module functions inherited from IModule
}
Implementation Example: Token Receiver Fallback
Based on the provided MockDefaultFallback implementation:
contract TokenReceiverFallback is
IERC721Receiver,
IERC1155Receiver,
IFallback
{
// Interface IDs
bytes4 private constant _INTERFACE_ID_ERC721_RECEIVER =
type(IERC721Receiver).interfaceId;
bytes4 private constant _INTERFACE_ID_ERC1155_RECEIVER =
type(IERC1155Receiver).interfaceId;
bytes4 private constant _INTERFACE_ID_ERC165 = type(IERC165).interfaceId;
// Events
event ERC721Received(
address operator,
address from,
uint256 tokenId,
bytes data
);
event ERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes data
);
event ERC1155BatchReceived(
address operator,
address from,
uint256[] ids,
uint256[] values,
bytes data
);
// Interface support check
function supportsInterface(
bytes4 interfaceId
) external view virtual returns (bool) {
return
interfaceId == _INTERFACE_ID_ERC721_RECEIVER ||
interfaceId == _INTERFACE_ID_ERC1155_RECEIVER ||
interfaceId == _INTERFACE_ID_ERC165;
}
// Token reception handlers
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external override returns (bytes4) {
emit ERC721Received(operator, from, tokenId, data);
return this.onERC721Received.selector;
}
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external override returns (bytes4) {
emit ERC1155Received(operator, from, id, value, data);
return this.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external override returns (bytes4) {
emit ERC1155BatchReceived(operator, from, ids, values, data);
return this.onERC1155BatchReceived.selector;
}
// Core Module Functions
function onInstall(bytes calldata) external override {}
function onUninstall(bytes calldata) external override {}
function isModuleType(uint256 moduleTypeId) external view returns (bool) {
return moduleTypeId == MODULE_TYPE_FALLBACK;
}
function isInitialized(address) external pure returns (bool) {
return true;
}
}
Extended Implementation: Logging Fallback
contract LoggingFallback is IFallback {
// Events for tracking unknown calls
event UnknownCallReceived(
address indexed sender,
uint256 value,
bytes data
);
event FallbackExecuted(
address indexed sender,
bool success,
bytes result
);
// State tracking
mapping(address => uint256) public callCount;
mapping(bytes4 => bool) public knownSelectors;
function handleUnknownCall(
address sender,
uint256 value,
bytes calldata data
) external returns (bool, bytes memory) {
// Log the unknown call
emit UnknownCallReceived(sender, value, data);
// Update call statistics
callCount[sender]++;
// Handle or forward the call as needed
return (true, "");
}
}
Common Use Cases
-
Token Reception
- ERC721 token handling
- ERC1155 token handling
- Custom token support
-
Fallback Behavior
- Unknown call logging
- Default responses
- Call forwarding
-
Security Features
- Call filtering
- Access control
- Activity monitoring
Security Considerations
-
Token Handling
- Safe token reception
- Proper event emission
- State consistency
-
Unknown Calls
- Parameter validation
- Selective handling
- Safe execution
-
Access Control
- Call authorization
- Value handling
- State protection
Best Practices
-
Implementation Guidelines
- Complete interface support
- Proper event emission
- Clear documentation
-
Error Handling
- Graceful fallbacks
- Clear error messages
- State validation
-
Gas Optimization
- Efficient storage
- Minimal operations
- Clear patterns
Special Considerations
-
Token Standards
- Support multiple standards
- Proper interface declaration
- Complete implementation
-
Unknown Calls
- Safe handling
- Proper logging
- Clear responses
-
State Management
- Consistent updates
- Safe operations
- Clear tracking